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