MotorSignal-App/test/route_models_test.dart

199 lines
6.5 KiB
Dart

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'));
});
});
}