import 'package:flutter_test/flutter_test.dart'; import 'package:motorcycle_dash/services/routes/route_models.dart'; void main() { group('RouteStop & RouteStopType tests', () { test('RouteStop serialization round-trip', () { const stop = RouteStop( id: 'stop-1', latitude: 37.7749, longitude: -122.4194, displayName: 'San Francisco Hub', stopType: RouteStopType.origin, orderIndex: 0, notes: 'Meet at 9 AM', ); final json = stop.toJson(); final fromJson = RouteStop.fromJson(json); expect(fromJson.id, equals('stop-1')); expect(fromJson.latitude, equals(37.7749)); expect(fromJson.longitude, equals(-122.4194)); expect(fromJson.displayName, equals('San Francisco Hub')); expect(fromJson.stopType, equals(RouteStopType.origin)); expect(fromJson.orderIndex, equals(0)); expect(fromJson.notes, equals('Meet at 9 AM')); expect(fromJson, equals(stop)); }); test('RouteStop copyWith preserves and modifies fields', () { const stop = RouteStop( id: 'stop-1', latitude: 37.7749, longitude: -122.4194, displayName: 'SF', stopType: RouteStopType.origin, orderIndex: 0, ); final updated = stop.copyWith( displayName: 'SF City Hall', orderIndex: 1, stopType: RouteStopType.waypoint, ); expect(updated.id, equals('stop-1')); expect(updated.displayName, equals('SF City Hall')); expect(updated.orderIndex, equals(1)); expect(updated.stopType, equals(RouteStopType.waypoint)); expect(updated.latitude, equals(37.7749)); }); test('RouteStopType labels', () { expect(RouteStopType.origin.label, equals('Start / Origin')); expect(RouteStopType.waypoint.label, equals('Waypoint')); expect(RouteStopType.fuel.label, equals('Fuel Stop')); expect(RouteStopType.rest.label, equals('Rest Area')); expect(RouteStopType.food.label, equals('Food & Drink')); expect(RouteStopType.scenic.label, equals('Scenic Overlook')); expect(RouteStopType.regroup.label, equals('Regroup Point')); expect(RouteStopType.destination.label, equals('Destination')); }); }); group('MotorSignalRoute domain model tests', () { final now = DateTime.utc(2026, 9, 4, 12, 0, 0); test('calculates straight-line distance correctly via Haversine', () { final route = MotorSignalRoute( id: 'route-sf-sj', ownerUid: 'alice', title: 'SF to San Jose Run', createdAt: now, updatedAt: now, stops: const [ RouteStop( id: 'stop-0', latitude: 37.7749, longitude: -122.4194, displayName: 'SF Start', stopType: RouteStopType.origin, orderIndex: 0, ), RouteStop( id: 'stop-1', latitude: 37.4419, longitude: -122.1430, displayName: 'Palo Alto', stopType: RouteStopType.waypoint, orderIndex: 1, ), RouteStop( id: 'stop-2', latitude: 37.3382, longitude: -121.8863, displayName: 'San Jose Finish', stopType: RouteStopType.destination, orderIndex: 2, ), ], ); expect(route.stops.length, equals(3)); expect(route.previewPoints.length, equals(3)); expect(route.totalDistanceMeters, greaterThan(65000)); expect(route.totalDistanceMeters, lessThan(85000)); expect(route.distanceMiles, greaterThan(40)); expect(route.distanceMiles, lessThan(55)); expect(route.formattedDistanceMiles, contains('mi')); expect(route.formattedDistanceKm, contains('km')); }); test('empty or single stop route has 0 distance', () { final emptyRoute = MotorSignalRoute( id: 'route-empty', ownerUid: 'alice', title: 'Empty Route', createdAt: now, updatedAt: now, stops: const [], ); expect(emptyRoute.totalDistanceMeters, equals(0.0)); expect(emptyRoute.distanceMiles, equals(0.0)); final singleStopRoute = MotorSignalRoute( id: 'route-single', ownerUid: 'alice', title: 'Single Stop Route', createdAt: now, updatedAt: now, stops: const [ RouteStop( id: 'stop-0', latitude: 37.7749, longitude: -122.4194, displayName: 'Solo', stopType: RouteStopType.origin, orderIndex: 0, ), ], ); expect(singleStopRoute.totalDistanceMeters, equals(0.0)); expect(singleStopRoute.distanceMiles, equals(0.0)); }); test('MotorSignalRoute serialization round-trip', () { final route = MotorSignalRoute( id: 'route-1', ownerUid: 'alice', title: 'Skyline Ridge', description: 'Twisty canyon ride', visibility: RouteVisibility.groupOnly, source: RouteSource.planner, attachedGroupRideId: 'group-ride-123', createdAt: now, updatedAt: now, stops: const [ RouteStop( id: 'stop-1', latitude: 37.4, longitude: -122.2, displayName: 'Alice\'s', stopType: RouteStopType.origin, orderIndex: 0, ), RouteStop( id: 'stop-2', latitude: 37.2, longitude: -122.1, displayName: 'Vista Point', stopType: RouteStopType.destination, orderIndex: 1, ), ], ); final json = route.toJson(); final fromJson = MotorSignalRoute.fromJson(json); expect(fromJson.id, equals('route-1')); expect(fromJson.ownerUid, equals('alice')); expect(fromJson.title, equals('Skyline Ridge')); expect(fromJson.description, equals('Twisty canyon ride')); expect(fromJson.visibility, equals(RouteVisibility.groupOnly)); expect(fromJson.source, equals(RouteSource.planner)); expect(fromJson.attachedGroupRideId, equals('group-ride-123')); expect(fromJson.stops.length, equals(2)); expect(fromJson.stops[0].displayName, equals('Alice\'s')); expect(fromJson.stops[1].displayName, equals('Vista Point')); }); test('RouteVisibility labels', () { expect(RouteVisibility.private.label, equals('Private')); expect(RouteVisibility.groupOnly.label, equals('Group Ride Only')); expect(RouteVisibility.public.label, equals('Public')); }); }); }