import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:motorcycle_dash/services/alerts/road_alert_models.dart'; import 'package:motorcycle_dash/services/alerts/tomtom_road_alert_provider.dart'; import 'package:motorcycle_dash/services/alerts/local_road_alert_provider.dart'; import 'package:motorcycle_dash/services/alerts/road_alert_providers.dart'; import 'package:motorcycle_dash/services/alerts/road_alert_service.dart'; import 'package:motorcycle_dash/services/field_test/field_test_logger.dart'; import 'package:motorcycle_dash/models/field_test_event.dart'; class _NoOpFieldTestLogger extends Fake implements FieldTestLogger { @override void log({ required FieldTestEventType eventType, required EventSeverity severity, required String message, int? rideId, DateTime? timestamp, DateTime? telemetryTimestamp, int? gpsAgeMs, double? speed, double? latitude, double? longitude, double? gpsAccuracy, double? leanAngle, double? longitudinalG, double? lateralG, double? overallConfidence, Map? metadata, }) {} } void main() { TestWidgetsFlutterBinding.ensureInitialized(); const flutterTtsChannel = MethodChannel('flutter_tts'); setUpAll(() { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler(flutterTtsChannel, (call) async { switch (call.method) { case 'setLanguage': case 'setSpeechRate': case 'setVolume': case 'speak': case 'stop': return 1; default: return null; } }); }); tearDownAll(() { TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .setMockMethodCallHandler(flutterTtsChannel, null); }); group('Road Alert System Tests', () { test('RoadAlertCategory display names and colors', () { expect(RoadAlertCategory.police.displayName, equals('Police')); expect(RoadAlertCategory.accident.displayName, equals('Accident')); expect(RoadAlertCategory.hazard.displayName, equals('Hazard')); expect(RoadAlertCategory.police.color, isNotNull); expect(RoadAlertCategory.accident.icon, isNotNull); }); test('TomTomRoadAlertProvider capability advertising', () { final provider = TomTomRoadAlertProvider(); expect(provider.id, equals('tomtom')); expect(provider.name, equals('TomTom Traffic')); // Verify TomTom explicitly advertises its supported categories (No police/speed-traps) expect(provider.supportedCategories, contains(RoadAlertCategory.accident)); expect(provider.supportedCategories, contains(RoadAlertCategory.hazard)); expect(provider.supportedCategories, contains(RoadAlertCategory.construction)); expect(provider.supportedCategories, contains(RoadAlertCategory.roadClosure)); expect(provider.supportedCategories, contains(RoadAlertCategory.traffic)); expect(provider.supportedCategories, isNot(contains(RoadAlertCategory.police))); expect(provider.supportedCategories, isNot(contains(RoadAlertCategory.speedCamera))); }); test('LocalRoadAlertProvider returns demo alerts', () async { final localProvider = LocalRoadAlertProvider(); final alerts = await localProvider.getAlerts( latitude: 37.7749, longitude: -122.4194, radiusMeters: 1000.0, ); expect(alerts.isNotEmpty, isTrue); expect(alerts.any((a) => a.category == RoadAlertCategory.hazard), isTrue); expect(alerts.any((a) => a.category == RoadAlertCategory.construction), isTrue); }); test('Road alert providers & setting defaults', () { SharedPreferences.setMockInitialValues({}); final container = ProviderContainer(); addTearDown(container.dispose); expect(container.read(roadAlertsEnabledProvider), isTrue); expect(container.read(audioAlertsEnabledProvider), isTrue); expect(container.read(alertRadiusMetersProvider), equals(804.7)); expect(container.read(tomtomApiKeyProvider), isEmpty); expect(container.read(tomtomStatusProvider), equals(RoadAlertProviderStatus.notConfigured)); }); test('RoadAlertService dismissAlert and clearAllAlerts function correctly', () async { SharedPreferences.setMockInitialValues({}); final container = ProviderContainer( overrides: [ fieldTestLoggerProvider.overrideWithValue(_NoOpFieldTestLogger()), ], ); addTearDown(container.dispose); final service = container.read(roadAlertServiceProvider); final future1 = service.alertsStream.first; service.triggerTestAlert(category: RoadAlertCategory.police); final alerts1 = await future1; expect(alerts1.isNotEmpty, isTrue); final alertId = alerts1.first.id; final future2 = service.alertsStream.first; service.dismissAlert(alertId); final alerts2 = await future2; expect(alerts2.any((a) => a.id == alertId), isFalse); final future3 = service.alertsStream.first; service.triggerTestAlert(category: RoadAlertCategory.hazard); final alerts3 = await future3; expect(alerts3.isNotEmpty, isTrue); final future4 = service.alertsStream.first; service.clearAllAlerts(); final alerts4 = await future4; expect(alerts4.isEmpty, isTrue); }); }); }