mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
fix: Reset fallback sharing state
This commit is contained in:
@@ -1,13 +1,36 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:meshcore_sar_app/models/message.dart';
|
||||
import 'package:meshcore_sar_app/models/device_info.dart';
|
||||
import 'package:meshcore_sar_app/providers/app_provider.dart';
|
||||
import 'package:meshcore_sar_app/providers/channels_provider.dart';
|
||||
import 'package:meshcore_sar_app/providers/connection_provider.dart';
|
||||
import 'package:meshcore_sar_app/providers/contacts_provider.dart';
|
||||
import 'package:meshcore_sar_app/providers/drawing_provider.dart';
|
||||
import 'package:meshcore_sar_app/providers/image_provider.dart' as ip;
|
||||
import 'package:meshcore_sar_app/providers/messages_provider.dart';
|
||||
import 'package:meshcore_sar_app/providers/voice_provider.dart';
|
||||
import 'package:meshcore_sar_app/services/location_tracking_service.dart';
|
||||
import 'package:meshcore_sar_app/services/voice_codec_service.dart';
|
||||
import 'package:meshcore_sar_app/services/voice_player_service.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
Uint8List _ownPublicKey() =>
|
||||
Uint8List.fromList([1, 2, 3, 4, 5, 6, ...List<int>.filled(26, 0)]);
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
setUp(() {
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
final locationTrackingService = LocationTrackingService();
|
||||
locationTrackingService.fastLocationUpdatesEnabled = false;
|
||||
locationTrackingService.fastLocationChannelIdx = null;
|
||||
locationTrackingService.isTracking = false;
|
||||
});
|
||||
|
||||
group('AppProvider channel info handling', () {
|
||||
test('treats zeroed unnamed non-public channel as deleted', () {
|
||||
expect(AppProvider.isDeletedChannelInfo(2, '', Uint8List(16)), isTrue);
|
||||
@@ -145,4 +168,188 @@ void main() {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('AppProvider channel location sharing state', () {
|
||||
test('clears app fallback sharing state when device disconnects', () async {
|
||||
final harness = _AppProviderHarness(
|
||||
connectionProvider: _FakeConnectionProvider(isConnected: true),
|
||||
);
|
||||
final locationTrackingService = harness.appProvider.locationTrackingService;
|
||||
|
||||
await locationTrackingService.updateFastLocationChannelIdx(3);
|
||||
await locationTrackingService.setFastLocationUpdatesEnabled(true);
|
||||
|
||||
harness.connectionProvider.setConnected(false);
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
|
||||
expect(locationTrackingService.fastLocationUpdatesEnabled, isFalse);
|
||||
expect(locationTrackingService.fastLocationChannelIdx, isNull);
|
||||
expect(harness.appProvider.channelLocationSharingModeForChannel(3), isNull);
|
||||
|
||||
await harness.dispose();
|
||||
});
|
||||
|
||||
test('preserves hardware sharing state when device disconnects', () async {
|
||||
final harness = _AppProviderHarness(
|
||||
connectionProvider: _FakeConnectionProvider(
|
||||
isConnected: true,
|
||||
customVars: const {'gps': '1', 'fast_gps_channel': '7'},
|
||||
),
|
||||
);
|
||||
|
||||
await harness.appProvider.refreshChannelLocationSharingState();
|
||||
|
||||
expect(
|
||||
harness.appProvider.channelLocationSharingModeForChannel(7),
|
||||
ChannelLocationSharingMode.hardware,
|
||||
);
|
||||
|
||||
harness.connectionProvider.setConnected(false);
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
|
||||
expect(
|
||||
harness.appProvider.channelLocationSharingModeForChannel(7),
|
||||
ChannelLocationSharingMode.hardware,
|
||||
);
|
||||
|
||||
await harness.dispose();
|
||||
});
|
||||
|
||||
test('clears app fallback sharing state when device connects', () async {
|
||||
final harness = _AppProviderHarness(
|
||||
connectionProvider: _FakeConnectionProvider(isConnected: false),
|
||||
);
|
||||
final locationTrackingService = harness.appProvider.locationTrackingService;
|
||||
|
||||
await locationTrackingService.updateFastLocationChannelIdx(5);
|
||||
await locationTrackingService.setFastLocationUpdatesEnabled(true);
|
||||
|
||||
harness.connectionProvider.setConnected(true);
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
|
||||
expect(locationTrackingService.fastLocationUpdatesEnabled, isFalse);
|
||||
expect(locationTrackingService.fastLocationChannelIdx, isNull);
|
||||
expect(harness.appProvider.channelLocationSharingModeForChannel(5), isNull);
|
||||
|
||||
await harness.dispose();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class _AppProviderHarness {
|
||||
final _FakeConnectionProvider connectionProvider;
|
||||
final ContactsProvider contactsProvider;
|
||||
final MessagesProvider messagesProvider;
|
||||
final DrawingProvider drawingProvider;
|
||||
final ChannelsProvider channelsProvider;
|
||||
final VoiceProvider voiceProvider;
|
||||
final ip.ImageProvider imageProvider;
|
||||
late final AppProvider appProvider;
|
||||
|
||||
_AppProviderHarness({required this.connectionProvider})
|
||||
: contactsProvider = ContactsProvider(),
|
||||
messagesProvider = MessagesProvider(),
|
||||
drawingProvider = DrawingProvider(),
|
||||
channelsProvider = ChannelsProvider(),
|
||||
voiceProvider = VoiceProvider(
|
||||
codec: VoiceCodecService(),
|
||||
player: _FakeVoicePlayerService(),
|
||||
),
|
||||
imageProvider = ip.ImageProvider() {
|
||||
appProvider = AppProvider(
|
||||
connectionProvider: connectionProvider,
|
||||
contactsProvider: contactsProvider,
|
||||
messagesProvider: messagesProvider,
|
||||
drawingProvider: drawingProvider,
|
||||
channelsProvider: channelsProvider,
|
||||
voiceProvider: voiceProvider,
|
||||
imageProvider: imageProvider,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
if (appProvider.trafficStatsReportingService.isInitialized) {
|
||||
break;
|
||||
}
|
||||
await Future<void>.delayed(const Duration(milliseconds: 10));
|
||||
}
|
||||
appProvider.dispose();
|
||||
voiceProvider.dispose();
|
||||
imageProvider.dispose();
|
||||
drawingProvider.dispose();
|
||||
messagesProvider.dispose();
|
||||
contactsProvider.dispose();
|
||||
connectionProvider.dispose();
|
||||
channelsProvider.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class _FakeConnectionProvider extends ConnectionProvider {
|
||||
DeviceInfo _deviceInfo;
|
||||
|
||||
_FakeConnectionProvider({
|
||||
required bool isConnected,
|
||||
Map<String, String>? customVars,
|
||||
}) : _deviceInfo = DeviceInfo(
|
||||
connectionState: isConnected
|
||||
? ConnectionState.connected
|
||||
: ConnectionState.disconnected,
|
||||
),
|
||||
_customVars = customVars ?? <String, String>{};
|
||||
|
||||
Map<String, String> _customVars;
|
||||
|
||||
@override
|
||||
DeviceInfo get deviceInfo => _deviceInfo;
|
||||
|
||||
void setConnected(bool isConnected) {
|
||||
_deviceInfo = _deviceInfo.copyWith(
|
||||
connectionState: isConnected
|
||||
? ConnectionState.connected
|
||||
: ConnectionState.disconnected,
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, String>> getCustomVars() async =>
|
||||
Map<String, String>.from(_customVars);
|
||||
}
|
||||
|
||||
class _FakeVoicePlayerService implements VoicePlayerService {
|
||||
final StreamController<void> _events = StreamController<void>.broadcast();
|
||||
bool _isPlaying = false;
|
||||
|
||||
@override
|
||||
bool get isPlaying => _isPlaying;
|
||||
|
||||
@override
|
||||
Duration get position => Duration.zero;
|
||||
|
||||
@override
|
||||
Duration get duration => Duration.zero;
|
||||
|
||||
@override
|
||||
Stream<void> get events => _events.stream;
|
||||
|
||||
@override
|
||||
Future<void> play(Int16List pcmSamples, {required int sampleRateHz}) async {
|
||||
_isPlaying = true;
|
||||
_events.add(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
_isPlaying = false;
|
||||
_events.add(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_events.close();
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user