158 lines
5.6 KiB
Dart
158 lines
5.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:motorcycle_dash/core/theme/theme_extensions.dart';
|
|
import 'package:motorcycle_dash/services/map/map_provider_interface.dart';
|
|
import 'package:motorcycle_dash/services/routes/route_models.dart';
|
|
import 'package:motorcycle_dash/features/routes/models/route_curvature_analysis.dart';
|
|
import 'package:motorcycle_dash/features/routes/widgets/curviness_priority_selector.dart';
|
|
import 'package:motorcycle_dash/features/routes/widgets/route_curvature_summary_card.dart';
|
|
import 'package:motorcycle_dash/features/routes/widgets/route_elevation_chart.dart';
|
|
|
|
void main() {
|
|
group('MOB-17: Route Curvature & Twistiness Analysis Model', () {
|
|
test('analyzes polyline geometry and classifies corners and switchbacks', () {
|
|
// Create a winding mountain path with hairpin turns
|
|
final points = [
|
|
const AppLatLng(37.7749, -122.4194),
|
|
const AppLatLng(37.7760, -122.4180),
|
|
const AppLatLng(37.7755, -122.4160), // sharp right bend
|
|
const AppLatLng(37.7770, -122.4165), // sharp left hairpin
|
|
const AppLatLng(37.7780, -122.4140),
|
|
const AppLatLng(37.7795, -122.4145),
|
|
];
|
|
|
|
final report = RouteCurvatureReport.analyze(
|
|
geometry: points,
|
|
priority: CurvinessPriority.curvy,
|
|
);
|
|
|
|
expect(report.totalCorners, greaterThan(0));
|
|
expect(report.twistinessIndex, greaterThan(1.0));
|
|
expect(report.elevationProfile, isNotEmpty);
|
|
expect(report.totalElevationGainMeters, greaterThan(0.0));
|
|
expect(report.formattedCornerCount, contains('Corners'));
|
|
expect(report.formattedElevationGain, contains('ft'));
|
|
});
|
|
|
|
test('priority multiplier scales twistiness for Extreme Passes', () {
|
|
final stops = [
|
|
const RouteStop(id: 's1', displayName: 'Base', latitude: 36.1, longitude: -118.2),
|
|
const RouteStop(id: 's2', displayName: 'Ridge', latitude: 36.2, longitude: -118.3),
|
|
const RouteStop(id: 's3', displayName: 'Peak', latitude: 36.3, longitude: -118.4),
|
|
];
|
|
|
|
final standardReport = RouteCurvatureReport.analyze(
|
|
geometry: const [],
|
|
stops: stops,
|
|
priority: CurvinessPriority.standard,
|
|
);
|
|
|
|
final extremeReport = RouteCurvatureReport.analyze(
|
|
geometry: const [],
|
|
stops: stops,
|
|
priority: CurvinessPriority.extremePasses,
|
|
);
|
|
|
|
expect(extremeReport.twistinessIndex, greaterThan(standardReport.twistinessIndex));
|
|
expect(extremeReport.totalCorners, greaterThanOrEqualTo(standardReport.totalCorners));
|
|
});
|
|
});
|
|
|
|
group('MOB-17: Curvy Route Widgets Rendering', () {
|
|
const colors = MotorSignalThemeColors.dark;
|
|
|
|
testWidgets('CurvinessPrioritySelector switches between priorities', (tester) async {
|
|
CurvinessPriority selected = CurvinessPriority.standard;
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Scaffold(
|
|
body: StatefulBuilder(
|
|
builder: (context, setState) {
|
|
return CurvinessPrioritySelector(
|
|
selected: selected,
|
|
onChanged: (p) => setState(() => selected = p),
|
|
colors: colors,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(find.text('CURVINESS PRIORITY'), findsOneWidget);
|
|
expect(find.text('Standard'), findsOneWidget);
|
|
expect(find.text('Curvy'), findsOneWidget);
|
|
expect(find.text('Extreme Passes'), findsOneWidget);
|
|
|
|
await tester.tap(find.text('Curvy'));
|
|
await tester.pumpAndSettle();
|
|
expect(selected, CurvinessPriority.curvy);
|
|
|
|
await tester.tap(find.text('Extreme Passes'));
|
|
await tester.pumpAndSettle();
|
|
expect(selected, CurvinessPriority.extremePasses);
|
|
});
|
|
|
|
testWidgets('RouteElevationChart displays gain, loss, and distance labels', (tester) async {
|
|
final report = RouteCurvatureReport.analyze(
|
|
geometry: [
|
|
const AppLatLng(34.05, -118.25),
|
|
const AppLatLng(34.10, -118.30),
|
|
const AppLatLng(34.15, -118.35),
|
|
],
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Scaffold(
|
|
body: RouteElevationChart(
|
|
report: report,
|
|
colors: colors,
|
|
isDark: true,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(find.text('ELEVATION PROFILE'), findsOneWidget);
|
|
expect(find.textContaining('Gain: +'), findsOneWidget);
|
|
expect(find.textContaining('0.0 mi (Start)'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('RouteCurvatureSummaryCard displays total corners and twistiness index', (tester) async {
|
|
final report = RouteCurvatureReport.analyze(
|
|
geometry: [
|
|
const AppLatLng(37.77, -122.41),
|
|
const AppLatLng(37.80, -122.45),
|
|
const AppLatLng(37.82, -122.48),
|
|
],
|
|
priority: CurvinessPriority.curvy,
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
MaterialApp(
|
|
home: Scaffold(
|
|
body: SingleChildScrollView(
|
|
child: RouteCurvatureSummaryCard(
|
|
report: report,
|
|
colors: colors,
|
|
isDark: true,
|
|
showElevationChart: true,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
expect(find.text('CURVATURE & ELEVATION'), findsOneWidget);
|
|
expect(find.text('TOTAL CORNERS'), findsOneWidget);
|
|
expect(find.text('TWISTINESS INDEX'), findsOneWidget);
|
|
expect(find.text('Hairpins'), findsOneWidget);
|
|
expect(find.text('Bends'), findsOneWidget);
|
|
expect(find.text('Sweepers'), findsOneWidget);
|
|
expect(find.text('ELEVATION PROFILE'), findsOneWidget);
|
|
});
|
|
});
|
|
}
|