MotorSignal-App/test/performance_launch_curve_da...

154 lines
5.5 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/features/performance/models/density_altitude_calculator.dart';
import 'package:motorcycle_dash/features/performance/models/performance_launch_models.dart';
import 'package:motorcycle_dash/features/performance/widgets/density_altitude_card.dart';
import 'package:motorcycle_dash/features/performance/widgets/launch_curve_chart.dart';
void main() {
group('MOB-09: Density Altitude (DA) Barometric Calculations', () {
test('calculates standard sea level atmospheric density altitude', () {
final da = DensityAltitudeCalculator.calculate(
elevationMeters: 0.0,
temperatureCelsius: 15.0,
barometricPressureHpa: 1013.25,
);
expect(da.elevationFeet, 0.0);
expect(da.pressureAltitudeFeet, 0.0);
expect(da.densityAltitudeFeet.round(), 0);
expect(da.relativeAirDensityPercent.round(), 100);
expect(da.rating, 'Mineshaft Air');
expect(da.horsepowerImpact, contains('HP Gain'));
});
test('calculates high elevation thin air DA with horsepower reduction', () {
// 1,800m elevation (~5,900 ft) at 32°C (90°F) hot day
final da = DensityAltitudeCalculator.calculate(
elevationMeters: 1800.0,
temperatureCelsius: 32.0,
barometricPressureHpa: 1005.0,
);
expect(da.densityAltitudeFeet, greaterThan(7000.0));
expect(da.relativeAirDensityPercent, lessThan(85.0));
expect(da.rating, 'Thin Air (High DA)');
expect(da.horsepowerImpact, contains('HP Loss'));
});
test('formats temperature in Fahrenheit and pressure in inHg correctly', () {
final da = DensityAltitudeCalculator.calculate(
elevationMeters: 300.0,
temperatureCelsius: 20.0,
barometricPressureHpa: 1013.25,
);
expect(da.temperatureFahrenheit, 68.0);
expect(da.pressureInHg, closeTo(29.92, 0.05));
expect(da.formattedDa, contains('ft'));
});
});
group('MOB-09: Launch Telemetry Points & Curve Synthesis', () {
test('synthesizes realistic motorcycle power curve when raw points empty', () {
final result = PerformanceLaunchResult(
mode: PerformanceLaunchMode.auto,
target: PerformanceLaunchTarget.sixty,
accelerationTimeSec: 3.42,
topSpeedReachedMph: 60.8,
timestamp: DateTime(2026, 9, 29, 12, 0),
);
final points = result.effectiveTelemetryPoints;
expect(points, isNotEmpty);
expect(points.first.elapsedSec, 0.0);
expect(points.last.elapsedSec, closeTo(3.42, 0.05));
expect(points.last.speedMph, closeTo(60.8, 0.5));
expect(result.peakLongitudinalG, greaterThan(1.0));
});
test('preserves high-frequency recorded points when present', () {
final customPoints = [
const LaunchTelemetryPoint(elapsedSec: 0.0, speedMph: 0.0, longitudinalG: 0.0),
const LaunchTelemetryPoint(elapsedSec: 1.0, speedMph: 35.0, longitudinalG: 1.25),
const LaunchTelemetryPoint(elapsedSec: 2.1, speedMph: 60.5, longitudinalG: 0.95),
];
final result = PerformanceLaunchResult(
mode: PerformanceLaunchMode.auto,
target: PerformanceLaunchTarget.sixty,
accelerationTimeSec: 2.1,
topSpeedReachedMph: 60.5,
telemetryPoints: customPoints,
timestamp: DateTime(2026, 9, 29, 12, 0),
);
expect(result.effectiveTelemetryPoints, equals(customPoints));
expect(result.peakLongitudinalG, 1.25);
});
});
group('MOB-09: Launch Curve & DA Widgets Rendering', () {
const colors = MotorSignalThemeColors.dark;
testWidgets('renders LaunchCurveChart with speed and G-force legends', (tester) async {
final result = PerformanceLaunchResult(
mode: PerformanceLaunchMode.auto,
target: PerformanceLaunchTarget.sixty,
accelerationTimeSec: 3.2,
topSpeedReachedMph: 61.2,
timestamp: DateTime(2026, 9, 29, 12, 0),
);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: SingleChildScrollView(
child: LaunchCurveChart(
result: result,
colors: colors,
isDark: true,
),
),
),
),
);
expect(find.text('LAUNCH CURVE & G-TRACE'), findsOneWidget);
expect(find.text('Speed (MPH)'), findsOneWidget);
expect(find.text('Accel (G)'), findsOneWidget);
expect(find.textContaining('PEAK: +'), findsOneWidget);
});
testWidgets('renders DensityAltitudeCard with DA and tuning toggle', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: SingleChildScrollView(
child: DensityAltitudeCard(
initialElevationMeters: 250.0,
colors: colors,
isDark: true,
),
),
),
),
);
expect(find.text('DENSITY ALTITUDE (DA)'), findsOneWidget);
expect(find.textContaining('air density'), findsOneWidget);
expect(find.text('Tune Baro'), findsOneWidget);
// Tap to expand tuning controls
await tester.tap(find.text('Tune Baro'));
await tester.pumpAndSettle();
expect(find.text('Track Elevation'), findsOneWidget);
expect(find.text('Ambient Temperature'), findsOneWidget);
expect(find.text('Barometric Pressure'), findsOneWidget);
});
});
}