import 'package:flutter_test/flutter_test.dart'; import 'package:motorcycle_dash/services/map/map_provider_interface.dart'; import 'package:motorcycle_dash/services/navigation/navigation_session_service.dart'; import 'package:motorcycle_dash/services/routes/route_models.dart'; import 'package:motorcycle_dash/services/routes/route_provider.dart'; void main() { group('NavigationSessionNotifier Tests', () { test('initial state is idle and empty', () { final notifier = NavigationSessionNotifier(); expect(notifier.state.status, equals(NavigationStatus.idle)); expect(notifier.state.isNavigating, isFalse); expect(notifier.state.hasActiveRoute, isFalse); expect(notifier.state.maneuvers, isEmpty); }); test('startNavigation initiates turn-by-turn guidance', () async { final notifier = NavigationSessionNotifier(); final maneuvers = [ const RouteManeuver( index: 0, instruction: 'Head north on Peachtree St', type: ManeuverType.depart, distanceMeters: 500.0, durationSeconds: 60, streetName: 'Peachtree St', location: AppLatLng(33.750, -84.388), ), const RouteManeuver( index: 1, instruction: 'Turn right on 10th St', type: ManeuverType.turnRight, distanceMeters: 1000.0, durationSeconds: 120, streetName: '10th St', location: AppLatLng(33.780, -84.385), ), const RouteManeuver( index: 2, instruction: 'Arrive at Piedmont Park', type: ManeuverType.arrive, distanceMeters: 0.0, durationSeconds: 0, streetName: 'Piedmont Park', location: AppLatLng(33.790, -84.370), ), ]; final calcResult = RouteCalculationResult( straightLineDistanceMeters: 1500.0, estimatedDistanceMeters: 1500.0, estimatedDurationSeconds: 180, geometry: const [ AppLatLng(33.750, -84.388), AppLatLng(33.780, -84.385), AppLatLng(33.790, -84.370), ], isStraightLine: false, providerName: 'AWS Location', maneuvers: maneuvers, ); await notifier.startNavigation( calculationResult: calcResult, destination: const ResolvedPlace( providerId: 'dest_1', displayName: 'Piedmont Park', latitude: 33.790, longitude: -84.370, ), ); expect(notifier.state.isNavigating, isTrue); expect(notifier.state.status, equals(NavigationStatus.navigating)); expect(notifier.state.maneuvers.length, equals(3)); expect(notifier.state.currentManeuverIndex, equals(0)); expect(notifier.state.currentManeuver?.instruction, equals('Head north on Peachtree St')); expect(notifier.state.nextManeuver?.instruction, equals('Turn right on 10th St')); expect(notifier.state.remainingDistanceMeters, equals(1500.0)); expect(notifier.state.remainingDurationSeconds, equals(180)); }); test('updateLocation advances maneuvers when rider approaches waypoint', () async { final notifier = NavigationSessionNotifier(); final maneuvers = [ const RouteManeuver( index: 0, instruction: 'Head north on Main', type: ManeuverType.depart, distanceMeters: 200.0, durationSeconds: 30, location: AppLatLng(33.7500, -84.3880), ), const RouteManeuver( index: 1, instruction: 'Turn left on Elm', type: ManeuverType.turnLeft, distanceMeters: 800.0, durationSeconds: 90, location: AppLatLng(33.7518, -84.3880), // ~200m north ), const RouteManeuver( index: 2, instruction: 'Arrive at destination', type: ManeuverType.arrive, distanceMeters: 0.0, durationSeconds: 0, location: AppLatLng(33.7518, -84.3960), ), ]; final calcResult = RouteCalculationResult( straightLineDistanceMeters: 1000.0, estimatedDistanceMeters: 1000.0, estimatedDurationSeconds: 120, geometry: const [ AppLatLng(33.7500, -84.3880), AppLatLng(33.7518, -84.3880), AppLatLng(33.7518, -84.3960), ], isStraightLine: false, providerName: 'AWS Location', maneuvers: maneuvers, ); await notifier.startNavigation(calculationResult: calcResult); // Rider is approaching starting waypoint (approx 100m south) notifier.updateLocation(const AppLatLng(33.7490, -84.3880), speedMph: 25.0); expect(notifier.state.currentManeuverIndex, equals(0)); // Rider reaches within 10 meters of maneuver 0 point notifier.updateLocation(const AppLatLng(33.7500, -84.3880), speedMph: 25.0); expect(notifier.state.currentManeuverIndex, equals(1)); expect(notifier.state.currentManeuver?.instruction, equals('Turn left on Elm')); // Pause and resume notifier.pauseNavigation(); expect(notifier.state.status, equals(NavigationStatus.paused)); expect(notifier.state.isNavigating, isFalse); notifier.resumeNavigation(); expect(notifier.state.status, equals(NavigationStatus.navigating)); // Stop navigation await notifier.stopNavigation(); expect(notifier.state.status, equals(NavigationStatus.idle)); expect(notifier.state.hasActiveRoute, isFalse); }); test('toggleTts toggles voice guidance', () { final notifier = NavigationSessionNotifier(); expect(notifier.state.ttsEnabled, isTrue); notifier.toggleTts(); expect(notifier.state.ttsEnabled, isFalse); notifier.toggleTts(); expect(notifier.state.ttsEnabled, isTrue); }); }); }