154 lines
5.5 KiB
Dart
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);
|
|
});
|
|
});
|
|
}
|