130 lines
5.2 KiB
Dart
130 lines
5.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:motorcycle_dash/core/theme/theme.dart';
|
|
import 'package:motorcycle_dash/features/map/widgets/road_alert_diagnostics_sheet.dart';
|
|
import 'package:motorcycle_dash/services/alerts/road_alert_models.dart';
|
|
import 'package:motorcycle_dash/services/alerts/road_alert_providers.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
Widget buildTestDiagnosticsSheet({
|
|
required RoadAlertDiagnostics diagnostics,
|
|
}) {
|
|
return ProviderScope(
|
|
overrides: [
|
|
roadAlertDiagnosticsProvider.overrideWith(
|
|
(ref) => RoadAlertDiagnosticsNotifier()..updateDiagnostics(diagnostics),
|
|
),
|
|
],
|
|
child: MaterialApp(
|
|
theme: AppTheme.darkTheme,
|
|
home: Scaffold(
|
|
body: Center(
|
|
child: Builder(
|
|
builder: (context) => ElevatedButton(
|
|
key: const ValueKey('open_diagnostics_btn'),
|
|
onPressed: () => RoadAlertDiagnosticsSheet.show(context),
|
|
child: const Text('Open Diagnostics'),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void configureViewport(WidgetTester tester, double width, double height) {
|
|
tester.view.physicalSize = Size(width, height);
|
|
tester.view.devicePixelRatio = 1.0;
|
|
}
|
|
|
|
group('Road Alert Diagnostics Model & Sheet Responsive Tests', () {
|
|
final now = DateTime(2026, 10, 13, 14, 30, 0);
|
|
|
|
final testDiagnostics = RoadAlertDiagnostics(
|
|
providerStatus: RoadAlertProviderStatus.connected,
|
|
isLive: true,
|
|
lastFetchTime: now,
|
|
lastSuccessfulFetchTime: now,
|
|
lastRequestedArea: '34.05° N, 84.40° W (25.0 km radius)',
|
|
rawReportsCount: 24,
|
|
normalizedAcceptedCount: 18,
|
|
displayedOnMapCount: 14,
|
|
dashboardEligibleCount: 3,
|
|
audioCandidateCount: 1,
|
|
activeRouteRelevance: true,
|
|
locationFreshnessState: 'fresh',
|
|
lastLocationAgeSeconds: 0.8,
|
|
locationAccuracyMeters: 8.5,
|
|
directionRejectedCount: 4,
|
|
distanceRejectedCount: 7,
|
|
staleGpsRejectedCount: 0,
|
|
lastDashboardAlertPresented: 'Police • 0.4 mi Ahead',
|
|
lastAudioWarningIssued: 'Police • 250 ft Ahead',
|
|
rejectedReasons: {
|
|
'stale_or_expired': 2,
|
|
'category_disabled': 1,
|
|
'out_of_tactical_range': 3,
|
|
},
|
|
);
|
|
|
|
test('RoadAlertDiagnostics correctly models all decoupled pipeline and GPS fields', () {
|
|
expect(testDiagnostics.dashboardEligibleCount, equals(3));
|
|
expect(testDiagnostics.audioCandidateCount, equals(1));
|
|
expect(testDiagnostics.activeRouteRelevance, isTrue);
|
|
expect(testDiagnostics.locationFreshnessState, equals('fresh'));
|
|
expect(testDiagnostics.lastLocationAgeSeconds, equals(0.8));
|
|
expect(testDiagnostics.locationAccuracyMeters, equals(8.5));
|
|
expect(testDiagnostics.directionRejectedCount, equals(4));
|
|
expect(testDiagnostics.distanceRejectedCount, equals(7));
|
|
expect(testDiagnostics.staleGpsRejectedCount, equals(0));
|
|
expect(testDiagnostics.lastDashboardAlertPresented, equals('Police • 0.4 mi Ahead'));
|
|
expect(testDiagnostics.lastAudioWarningIssued, equals('Police • 250 ft Ahead'));
|
|
});
|
|
|
|
testWidgets('Renders cleanly on 400x800 portrait phone with zero overflow', (tester) async {
|
|
configureViewport(tester, 400, 800);
|
|
addTearDown(() => tester.view.resetPhysicalSize());
|
|
|
|
await tester.pumpWidget(buildTestDiagnosticsSheet(diagnostics: testDiagnostics));
|
|
await tester.tap(find.byKey(const ValueKey('open_diagnostics_btn')));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(tester.takeException(), isNull);
|
|
expect(find.text('ROAD ALERT DIAGNOSTICS'), findsOneWidget);
|
|
expect(find.text('PIPELINE STAGE METRICS'), findsOneWidget);
|
|
|
|
// Verify stage metrics grid tiles
|
|
expect(find.text('Raw Upstream'), findsOneWidget);
|
|
expect(find.text('Normalized'), findsOneWidget);
|
|
expect(find.text('Tactical (Map)'), findsOneWidget);
|
|
expect(find.text('Dashboard (2mi)'), findsOneWidget);
|
|
expect(find.text('Audio (400m)'), findsOneWidget);
|
|
|
|
// Verify metadata rows
|
|
expect(find.text('GPS Quality'), findsOneWidget);
|
|
expect(find.text('Corridor Filter Mode'), findsOneWidget);
|
|
expect(find.text('Last Dashboard Alert'), findsOneWidget);
|
|
expect(find.text('Last Audio Warning'), findsOneWidget);
|
|
expect(find.text('Distance Exceeds Dashboard (>2.0mi)'), findsOneWidget);
|
|
expect(find.text('Behind Rider / Off Route'), findsOneWidget);
|
|
});
|
|
|
|
testWidgets('Renders cleanly on 840x390 landscape phone with zero overflow', (tester) async {
|
|
configureViewport(tester, 840, 390);
|
|
addTearDown(() => tester.view.resetPhysicalSize());
|
|
|
|
await tester.pumpWidget(buildTestDiagnosticsSheet(diagnostics: testDiagnostics));
|
|
await tester.tap(find.byKey(const ValueKey('open_diagnostics_btn')));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(tester.takeException(), isNull);
|
|
expect(find.text('ROAD ALERT DIAGNOSTICS'), findsOneWidget);
|
|
expect(find.text('Dashboard (2mi)'), findsOneWidget);
|
|
expect(find.text('Audio (400m)'), findsOneWidget);
|
|
});
|
|
});
|
|
}
|