fix: Stabilize reported tests #31

ref: #32 #37
This commit is contained in:
Janez T
2026-04-26 08:24:07 +02:00
parent 2fe125d6ba
commit 0008eff1b8
6 changed files with 63 additions and 23 deletions

View File

@@ -1263,11 +1263,17 @@ class ContactsProvider with ChangeNotifier {
Map<String, dynamic>? existingExtraSensorData, Map<String, dynamic>? existingExtraSensorData,
Map<String, dynamic>? incomingExtraSensorData, Map<String, dynamic>? incomingExtraSensorData,
) { ) {
final merged = <String, dynamic>{...?existingExtraSensorData};
if (incomingExtraSensorData == null || incomingExtraSensorData.isEmpty) { if (incomingExtraSensorData == null || incomingExtraSensorData.isEmpty) {
return merged; return <String, dynamic>{...?existingExtraSensorData};
} }
final isFullTelemetryRefresh = incomingExtraSensorData.containsKey(
_rawTelemetryHexKey,
);
final merged = <String, dynamic>{
if (!isFullTelemetryRefresh) ...?existingExtraSensorData,
};
final incomingMetricFamilies = incomingExtraSensorData.keys final incomingMetricFamilies = incomingExtraSensorData.keys
.map(_telemetryMetricFamilyForKey) .map(_telemetryMetricFamilyForKey)
.whereType<String>() .whereType<String>()

View File

@@ -328,9 +328,16 @@ class _RecipientSelectorSheetState extends State<RecipientSelectorSheet> {
MessagesProvider? messagesProvider, MessagesProvider? messagesProvider,
) { ) {
final previewData = _channelPreviewData(context, channel, messagesProvider); final previewData = _channelPreviewData(context, channel, messagesProvider);
final sharingMode = context.watch<AppProvider>().channelLocationSharingModeForChannel( ChannelLocationSharingMode? sharingMode;
channel.publicKey.length > 1 ? channel.publicKey[1] : 0, try {
); sharingMode = context
.watch<AppProvider>()
.channelLocationSharingModeForChannel(
channel.publicKey.length > 1 ? channel.publicKey[1] : 0,
);
} on ProviderNotFoundException {
sharingMode = null;
}
return _buildRecipientCard( return _buildRecipientCard(
context: context, context: context,

View File

@@ -238,15 +238,27 @@ List<SensorMetricOption> sensorMetricOptionsFor(
final coreFieldKeys = <String>{ final coreFieldKeys = <String>{
if (batteryMilliVolts != null || batteryPercentage != null) if (batteryMilliVolts != null || batteryPercentage != null)
...extraSensorData?.keys.where( ...extraSensorData?.keys.where(
(k) => k.startsWith('voltage_') || k.startsWith('analog_input_'), (k) =>
_isSourceChannelMetric(extraSensorData, 'voltage', k) ||
_isSourceChannelMetric(extraSensorData, 'battery', k) ||
k.startsWith('analog_input_'),
) ?? ) ??
[], [],
if (temperature != null) if (temperature != null)
...extraSensorData?.keys.where((k) => k.startsWith('temperature_')) ?? [], ...extraSensorData?.keys.where(
(k) => _isSourceChannelMetric(extraSensorData, 'temperature', k),
) ??
[],
if (humidity != null) if (humidity != null)
...extraSensorData?.keys.where((k) => k.startsWith('humidity_')) ?? [], ...extraSensorData?.keys.where(
(k) => _isSourceChannelMetric(extraSensorData, 'humidity', k),
) ??
[],
if (pressure != null) if (pressure != null)
...extraSensorData?.keys.where((k) => k.startsWith('pressure_')) ?? [], ...extraSensorData?.keys.where(
(k) => _isSourceChannelMetric(extraSensorData, 'pressure', k),
) ??
[],
}; };
if (extraSensorData != null) { if (extraSensorData != null) {
@@ -3117,6 +3129,18 @@ int? _sourceChannelForField(
return null; return null;
} }
bool _isSourceChannelMetric(
Map<String, dynamic>? extraSensorData,
String fieldKey,
String metricKey,
) {
final sourceChannel = _sourceChannelForField(extraSensorData, fieldKey);
if (sourceChannel == null) {
return false;
}
return metricKey == '${fieldKey}_$sourceChannel';
}
String _resolvedMetricLabel( String _resolvedMetricLabel(
String fieldKey, String fieldKey,
String defaultLabel, { String defaultLabel, {

View File

@@ -926,7 +926,9 @@ void main() {
); );
provider.markMessageSent('m2', 88, 10); provider.markMessageSent('m2', 88, 10);
async.elapse(const Duration(milliseconds: 11)); final timeoutMs = provider.messages.single.suggestedTimeoutMs!;
async.elapse(Duration(milliseconds: timeoutMs + 1));
async.flushMicrotasks(); async.flushMicrotasks();
expect(provider.messages.single.retryAttempt, 1); expect(provider.messages.single.retryAttempt, 1);

View File

@@ -201,7 +201,10 @@ void main() {
addTearDown(tester.view.reset); addTearDown(tester.view.reset);
final connectionProvider = _TcpConnectableFakeConnectionProvider(); final connectionProvider = _TcpConnectableFakeConnectionProvider();
final networkScanner = _FakeNetworkScannerService(initiallyScanning: true); final networkScanner = _FakeNetworkScannerService(
initiallyScanning: true,
keepScanning: true,
);
await tester.pumpWidget( await tester.pumpWidget(
ChangeNotifierProvider<ConnectionProvider>.value( ChangeNotifierProvider<ConnectionProvider>.value(

View File

@@ -5,6 +5,7 @@ import 'package:http/http.dart' as http;
import 'package:http/testing.dart'; import 'package:http/testing.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:meshcore_sar_app/l10n/app_localizations.dart';
import 'package:meshcore_sar_app/services/traffic_stats_reporting_service.dart'; import 'package:meshcore_sar_app/services/traffic_stats_reporting_service.dart';
import 'package:meshcore_sar_app/widgets/settings/traffic_stats_reporting_section.dart'; import 'package:meshcore_sar_app/widgets/settings/traffic_stats_reporting_section.dart';
@@ -57,6 +58,8 @@ void main() {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: Scaffold( home: Scaffold(
body: ListenableBuilder( body: ListenableBuilder(
listenable: service, listenable: service,
@@ -68,27 +71,22 @@ void main() {
), ),
); );
expect(find.text('Anonymous RX stats reporting'), findsOneWidget); expect(find.text('Anonymous RX stats'), findsOneWidget);
expect( expect(find.text('Upload packet totals every 5 min'), findsOneWidget);
find.text(
'Upload RX live-traffic packet type and path mode totals to the fixed Cloudflare worker every 5 minutes.',
),
findsOneWidget,
);
expect(find.text('Reporting interval'), findsNothing); expect(find.text('Reporting interval'), findsNothing);
expect(service.isEnabled, isTrue); expect(service.isEnabled, isTrue);
await tester.tap(find.widgetWithText(TextButton, 'View'));
await tester.pump();
expect(launchedUrls, ['https://mcstats.dz0ny.dev']);
await tester.tap(find.byType(Switch)); await tester.tap(find.byType(Switch));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(service.isEnabled, isFalse); expect(service.isEnabled, isFalse);
expect(service.intervalMinutes, 5); expect(service.intervalMinutes, 5);
await tester.tap(find.widgetWithText(TextButton, 'View public stats'));
await tester.pump();
expect(launchedUrls, ['https://mcstats.dz0ny.dev']);
service.dispose(); service.dispose();
}); });
} }